#define _XOPEN_SOURCE
#include <stdio.h>
#include "hashmap.h"
#include "server.h"
#include <assert.h>
#include <errno.h>


int main() {
   
    // 初始化唤醒管道
    if (init_wakeup_pipe() != 0) {
        fprintf(stderr, "初始化唤醒管道失败，退出程序\n");
        return 1;  // 直接退出，不再执行后续 epoll_ctl 操作

    }

    // 设置信号处理
    struct sigaction sa = {0};
    sa.sa_handler = handle_signal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    // 创建会话哈希表
    hashmap_t *session_map = hashmap_create(16);
    if (!session_map) {
        perror("hashmap create failed");
        return 1;
    }

    // 创建监听套接字
    int listen_fd = create_and_bind();
    if (listen_fd == -1) {
        perror("create_and_bind failed");
        hashmap_destroy(session_map);
        return 1;
    }
    set_nonblocking(listen_fd);

    // 创建epoll实例
    int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        perror("epoll_create1 failed");
        close(listen_fd);
        hashmap_destroy(session_map);
        return 1;
    }
    global_epoll_fd = epoll_fd;  // 保存全局epoll句柄

    // 注册监听套接字到epoll
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listen_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) {
        perror("epoll_ctl add listen_fd failed");
        close(epoll_fd);
        close(listen_fd);
        hashmap_destroy(session_map);
        return 1;
    }

    // 将唤醒管道读端注册到epoll（用于信号唤醒）
    ev.events = EPOLLIN;
    ev.data.fd = wakeup_pipe[0];
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, wakeup_pipe[0], &ev) == -1) {
        perror("epoll_ctl add wakeup pipe failed");
        // 打印无效的 fd 用于调试
        fprintf(stderr, "wakeup pipe fd: %d\n", wakeup_pipe[0]);
        close(epoll_fd);
        close(listen_fd);
        close(wakeup_pipe[0]);
        close(wakeup_pipe[1]);
        hashmap_destroy(session_map);
        return 1;
    }

    // 初始化事件数组
    struct epoll_event *event_addr = (struct epoll_event*)malloc(sizeof(struct epoll_event) * event_count);
    if (!event_addr) {
        perror("malloc event_addr failed");
        close(epoll_fd);
        close(listen_fd);
        close(wakeup_pipe[0]);
        close(wakeup_pipe[1]);
        hashmap_destroy(session_map);
        return 1;
    }

    // 主事件循环
    while (!stop_server) {
        int nfds = epoll_wait(epoll_fd, event_addr, event_count, -1);
        if (nfds < 0) {
            if (errno == EINTR) continue;  // 被信号打断，重试
            perror("epoll_wait failed");
            break;
        }

        // 处理唤醒管道事件（清空数据，避免重复唤醒）
        for (int i = 0; i < nfds; i++) {
            if (event_addr[i].data.fd == wakeup_pipe[0]) {
                char buf[1024];
                // 读取所有数据，清空管道
                while (read(wakeup_pipe[0], buf, sizeof(buf)) > 0);
                if (stop_server) {
                    printf("Preparing to exit event loop...\n");
                    fflush(stdout);
                }
                continue;  // 不处理其他逻辑，继续循环检查stop_server
            }
        }

        // 动态扩容事件数组
        if ((size_t)nfds == event_count) {
            size_t new_count = event_count * 2;
            struct epoll_event *new_addr = realloc(event_addr, sizeof(*new_addr) * new_count);
            if (new_addr) {
                event_addr = new_addr;
                event_count = new_count;
                printf(">>> expanded event_addr to %d entries\n", event_count);
            } else {
                perror("realloc event_addr failed (continue with old size)");
            }
        }

        // 处理所有事件
        for (int i = 0; i < nfds; i++) {
            int fd = event_addr[i].data.fd;
            uint32_t evs = event_addr[i].events;

            // 忽略唤醒管道（已在上面处理）
            if (fd == wakeup_pipe[0]) continue;

            // 处理新连接
            if (fd == listen_fd) {
                struct sockaddr_in cli;
                socklen_t len = sizeof(cli);
                while (1) {
                    int conn_fd = accept(listen_fd, (struct sockaddr*)&cli, &len);
                    if (conn_fd < 0) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) break;
                        if (errno == EINTR) continue;
                        perror("accept failed");
                        break;
                    }
                    session_t *session = session_create(conn_fd);
                    if (!session) {
                        perror("session create failed");
                        close(conn_fd);  // 确保连接关闭
                        break;
                    }
                    set_nonblocking(conn_fd);
                    ev.events = EPOLLIN | EPOLLET;
                    ev.data.fd = conn_fd;
                    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) == -1) {
                        perror("epoll_ctl add conn_fd failed");
                        session_destroy(session, epoll_fd);
                        break;
                    }
                    hashmap_put_int(session_map, conn_fd, session);
                    printf("Accepted fd=%d\n", conn_fd);
                }
                continue;
            }

            // 处理已有连接事件
            session_t *sess = hashmap_get_int(session_map, fd);
            if (!sess) {
                printf("fd=%d not found in session_map, removing from epoll\n", fd);
                epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
                close(fd);  // 确保fd关闭
                continue;
            }

            // 处理错误事件
            if (evs & (EPOLLERR | EPOLLHUP)) {
                fprintf(stderr, "fd=%d error/hup event\n", fd);
                goto net_error;
            }

            // 处理读写事件
            if (evs & (EPOLLIN | EPOLLOUT)) {
                if (evs & EPOLLIN) {
                    while(1){
                        if (sess->recv_stage == NO_RECV || sess->recv_stage == HEAD_RECVING) {
                            int remain = HEAD_LEN - sess->head_buf->offset;
                            ssize_t read_len = read(fd, sess->head_buf->buf + sess->head_buf->offset, remain);
                            if (read_len < 0) {
                                if (errno == EAGAIN || errno == EWOULDBLOCK) break;
                                if (errno == EINTR) continue;
                                perror("read header failed");
                                goto net_error;
                            }
                            if (read_len == 0) {  // 对端关闭
                                goto net_error;
                            }
                            // 头部未接收完
                            if (read_len < remain) {
                                sess->recv_stage = HEAD_RECVING;
                                sess->head_buf->offset += read_len;
                                continue;
                            }
                            // 解析头部
                            uint8_t *hdr = sess->head_buf->buf;
                            uint16_t t, l;
                            memcpy(&t, hdr, sizeof(t));
                            memcpy(&l, hdr + 2, sizeof(l));
                            uint16_t msg_type = ntohs(t);
                            uint16_t body_len = ntohs(l);
                            if (body_len > BUFF_SIZE) {
                                printf("fd=%d body too big (%d > %d)\n", fd, body_len, BUFF_SIZE);
                                goto net_error;
                            }
                            printf("fd=%d received head: type=%d, len=%d\n", fd, msg_type, body_len);
                            fflush(stdout);
                            sess->recv_stage = BODY_RECVING;
                            sess->head_buf->offset += read_len;
                            sess->data_buf = malloc_data_buf(msg_type, body_len);
                            if (!sess->data_buf) {
                                perror("malloc_data_buf failed");
                                goto net_error;
                            }
                            continue;
                        }

                        if (sess->recv_stage == BODY_RECVING) {
                            int remain = sess->data_buf->data_len - sess->data_buf->offset;
                            ssize_t read_len = read(fd, sess->data_buf->buf + sess->data_buf->offset, remain);
                            if (read_len < 0) {
                                if (errno == EAGAIN || errno == EWOULDBLOCK) break;
                                if (errno == EINTR) continue;
                                perror("read body failed");
                                goto net_error;
                            }
                            if (read_len == 0) {  // 对端关闭
                                goto net_error;
                            }
                            sess->data_buf->offset += read_len;
                            if (read_len < remain) continue;  // 未读完
                            // 处理消息（回声功能）

                            uint16_t body_len = sess->data_buf->data_len;
                            uint16_t msg_type = sess->data_buf->type;

                            ssize_t send_result = async_send(sess, epoll_fd, evs, msg_type, body_len, sess->data_buf->buf);
                            if (send_result < 0) {
                                fprintf(stderr, "fd=%d 发送消息失败\n", fd);
                                goto net_error;
                            } else if (send_result == 0) {
                                printf("fd=%d 消息已加入发送队列\n", fd);
                            } else {
                                printf("fd=%d 已发送 %zd 字节\n", fd, send_result);
                            }
                            // size_t total_len = sizeof(uint16_t) * 2 + body_len;
                            // uint8_t *buf = malloc(total_len);
                            // if (buf) {
                            //     uint16_t net_type = htons(msg_type);
                            //     uint16_t net_len = htons(body_len);
                            //     memcpy(buf, &net_type, 2);
                            //     memcpy(buf + 2, &net_len, 2);
                            //     memcpy(buf + 4, sess->data_buf->buf, body_len);
                            //     write(fd, buf, total_len);  // 实际应处理write的返回值
                            //     free(buf);
                            // }
                            printf("fd=%d received body: \"%.*s\"\n", fd, (int)sess->data_buf->data_len, sess->data_buf->buf);
                            fflush(stdout);

                            
                            // 重置会话状态
                            dealloc_data_buf(sess->data_buf);
                            sess->data_buf = NULL;
                            sess->recv_stage = NO_RECV;
                            memset(sess->head_buf->buf, 0, HEAD_LEN);
                            sess->head_buf->offset = 0;
                            continue;
                        }
                    }
                    
                }

                if (evs & EPOLLOUT) {
                    handle_epollout(epoll_fd, fd, sess->send_que);
                }
                continue;
            }

            // 未处理的事件
            net_error:
                fprintf(stderr, "fd=%d unexpected event: 0x%x, cleaning up\n", fd, evs);
                session_destroy(sess, epoll_fd);
                hashmap_remove_int(session_map, fd);
        }
    }

    // 优雅退出：清理所有资源
    printf("\nStopping server, cleaning up resources...\n");
    fflush(stdout);

    // 1. 关闭监听套接字，停止接收新连接
    printf("Closing listening socket...\n");
    fflush(stdout);
    close(listen_fd);

    // 2. 遍历销毁所有会话
    printf("Closing all client connections...\n");
    fflush(stdout);
    int session_count = 0;
    for (size_t i = 0; i < session_map->bucket_count; i++) {
        hashmap_entry_t *entry = session_map->buckets[i];
        while (entry) {
            session_t *sess = (session_t*)entry->value;
            session_destroy(sess, epoll_fd);  // 内部需实现close(fd)和epoll_ctl_del
            entry = entry->next;
            session_count++;
        }
    }
    printf("Closed %d client connections\n", session_count);
    fflush(stdout);

    // 3. 释放动态分配的内存
    printf("Freeing allocated memory...\n");
    fflush(stdout);
    free(event_addr);
    hashmap_destroy(session_map);

    // 4. 关闭epoll和唤醒管道
    printf("Closing epoll and wakeup pipe...\n");
    fflush(stdout);
    close(epoll_fd);
    close(wakeup_pipe[0]);
    close(wakeup_pipe[1]);

    printf("Server exited gracefully\n");
    fflush(stdout);
    return 0;
}

// void test_hash(){
//     // 创建 16 桶的哈希表
//     hashmap_t *map = hashmap_create(16);
//     assert(map != NULL);

//     // --- 字符串键测试 ---
//     printf("=== String key tests ===\n");
//     assert(hashmap_get(map, "alpha") == NULL);
//     assert(hashmap_put(map, "alpha", (void*)"A") == 0);
//     assert(hashmap_put(map, "beta",  (void*)"B") == 0);
//     assert(hashmap_put(map, "gamma", (void*)"G") == 0);

//     // 重复插入同一个 key，覆盖旧值
//     assert(hashmap_put(map, "beta", (void*)"BB") == 0);

//     // 查询并打印
//     printf("alpha -> %s\n", (char*)hashmap_get(map, "alpha")); // A
//     printf("beta  -> %s\n", (char*)hashmap_get(map, "beta"));  // BB
//     printf("gamma -> %s\n", (char*)hashmap_get(map, "gamma")); // G

//     // 删除并确认
//     assert(hashmap_remove(map, "alpha") == 0);
//     assert(hashmap_get(map, "alpha") == NULL);

//     // --- 整数键测试 ---
//     printf("\n=== Integer key tests ===\n");
//     assert(hashmap_get_int(map, 10) == NULL);
//     assert(hashmap_put_int(map, 10, (void*)"ten") == 0);
//     assert(hashmap_put_int(map, 20, (void*)"twenty") == 0);
//     assert(hashmap_put_int(map, 30, (void*)"thirty") == 0);

//     // 覆盖测试
//     assert(hashmap_put_int(map, 20, (void*)"XX") == 0);

//     // 查询并打印
//     printf("10 -> %s\n", (char*)hashmap_get_int(map, 10));   // ten
//     printf("20 -> %s\n", (char*)hashmap_get_int(map, 20));   // XX
//     printf("30 -> %s\n", (char*)hashmap_get_int(map, 30));   // thirty

//     // 删除并确认
//     assert(hashmap_remove_int(map, 30) == 0);
//     assert(hashmap_get_int(map, 30) == NULL);

//     // --- 混合测试 ---
//     printf("\n=== Mixed key tests ===\n");
//     // 同时存在字符串 key 和 整数 key
//     assert(hashmap_put(map,   "100", (void*)"str100") == 0);
//     assert(hashmap_put_int(map, 100,   (void*)"int100") == 0);

//     printf("\"100\" -> %s\n", (char*)hashmap_get(map, "100"));      // str100
//     printf("100   -> %s\n", (char*)hashmap_get_int(map, 100));     // int100

//     // 清理
//     hashmap_destroy(map);
//     printf("\nAll tests passed!\n");
// }